package com.lysj.admin.master.common.spring.jpa;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReflectUtil;
import com.lysj.admin.master.common.web.ParamUtil;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @author zk
 * @description Springdata条件构造器
 * @create 2018-07-16 23:15
 **/
public class ConditionUtil {


    @SuppressWarnings("unchecked")
    public static Specification createBaseSpecification(final Object model) {
        Specification specification = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new LinkedList<>();
            // 得到类对象
            Class cls = model.getClass();
            /* 得到类中的所有属性集合 */
            Field[] fs = cls.getDeclaredFields();
            for (Field f : fs) {
                f.setAccessible(true);
                Object val = ReflectUtil.getFieldValue(model, f);
                if(val == null || val.toString().equals("")){
                    continue;
                }
                JpaPredicate jpaPredicate = f.getAnnotation(JpaPredicate.class);
                if (jpaPredicate != null) {
                    //若没有额外填写字段名，默认属性名为要查询的字段名
                    String propertyName = ParamUtil.isBlank(jpaPredicate.property()) ? f.getName() : jpaPredicate.property();
                    Path path = root.get(propertyName);
                    PredicateDTO predicateDTO = new PredicateDTO(path,val);
                    predicates.add(jpaPredicate.value().getPredicateFunc().apply(predicateDTO,criteriaBuilder));
//                    switch (jpaPredicate.value()) {
//                        case EQ:
//                            predicates.add(criteriaBuilder.equal(path, val));
//                            break;
//                        case NE:
//                            predicates.add(criteriaBuilder.notEqual(path, val));
//                            break;
//                        case GT:
//                            predicates.add(criteriaBuilder.greaterThan(path, (Comparable) val));
//                            break;
//                        case GE:
//                            predicates.add(criteriaBuilder.greaterThanOrEqualTo(path, (Comparable) val));
//                            break;
//                        case LT:
//                            predicates.add(criteriaBuilder.lessThan(path, (Comparable) val));
//                            break;
//                        case LE:
//                            predicates.add(criteriaBuilder.lessThanOrEqualTo(path, (Comparable) val));
//                            break;
//                        case F_LK:
//                            predicates.add(criteriaBuilder.like(path,"%"+val+"%"));
//                            break;
//                        case L_LK:
//                            predicates.add(criteriaBuilder.like(path,"%"+val));
//                            break;
//                        case R_LK:
//                            predicates.add(criteriaBuilder.like(path,val+"%"));
//                            break;
//                        case IN:
//                            predicates.add(path.in((Collection) val));
//                            break;
//                        case NI:
//                            predicates.add(path.in((Collection) val).not());
//                            break;
//                    }
                }
            }
            return criteriaBuilder.and(ArrayUtil.toArray(predicates,Predicate.class));
        };
        return specification;
    }
}
